feat: auto-generate harmonised, ergonomic SDKs across 12 languages#35
Draft
mridang wants to merge 787 commits into
Draft
feat: auto-generate harmonised, ergonomic SDKs across 12 languages#35mridang wants to merge 787 commits into
mridang wants to merge 787 commits into
Conversation
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
5166131 to
3cb26d3
Compare
1113be3 to
bc8fd3d
Compare
e134b80 to
f61e4ed
Compare
ace5c59 to
9039e83
Compare
mridang
added a commit
that referenced
this pull request
May 4, 2026
…, #35) - #2: Make Go ApiResult.Data nullable (*T pointer type) - #5: Dart caCertPath defaults to null instead of empty string - #9: Add toCookieValue to ObjectSerializer in all 12 languages - #14: Dart DefaultApiClient uses caCertPath with SecurityContext - #15: Fix Dart redirect handling (autoRedirect + maxRedirects) - #18: Route Dart/Rust path params through ValueSerializer.serializeStyled() - #26: Add default value support in Go, Rust, Swift, Dart, Elixir models - #35: Update Go version to 1.26 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58765c7 to
df347a4
Compare
mridang
added a commit
that referenced
this pull request
May 4, 2026
…, #35) - #2: Make Go ApiResult.Data nullable (*T pointer type) - #5: Dart caCertPath defaults to null instead of empty string - #9: Add toCookieValue to ObjectSerializer in all 12 languages - #14: Dart DefaultApiClient uses caCertPath with SecurityContext - #15: Fix Dart redirect handling (autoRedirect + maxRedirects) - #18: Route Dart/Rust path params through ValueSerializer.serializeStyled() - #26: Add default value support in Go, Rust, Swift, Dart, Elixir models - #35: Update Go version to 1.26 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
df347a4 to
642ef91
Compare
mridang
added a commit
that referenced
this pull request
May 4, 2026
…, #35) - #2: Make Go ApiResult.Data nullable (*T pointer type) - #5: Dart caCertPath defaults to null instead of empty string - #9: Add toCookieValue to ObjectSerializer in all 12 languages - #14: Dart DefaultApiClient uses caCertPath with SecurityContext - #15: Fix Dart redirect handling (autoRedirect + maxRedirects) - #18: Route Dart/Rust path params through ValueSerializer.serializeStyled() - #26: Add default value support in Go, Rust, Swift, Dart, Elixir models - #35: Update Go version to 1.26 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
642ef91 to
6713b61
Compare
mridang
added a commit
that referenced
this pull request
May 5, 2026
…, #35) - #2: Make Go ApiResult.Data nullable (*T pointer type) - #5: Dart caCertPath defaults to null instead of empty string - #9: Add toCookieValue to ObjectSerializer in all 12 languages - #14: Dart DefaultApiClient uses caCertPath with SecurityContext - #15: Fix Dart redirect handling (autoRedirect + maxRedirects) - #18: Route Dart/Rust path params through ValueSerializer.serializeStyled() - #26: Add default value support in Go, Rust, Swift, Dart, Elixir models - #35: Update Go version to 1.26 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6713b61 to
f6d73f3
Compare
mridang
added a commit
that referenced
this pull request
May 5, 2026
…, #35) - #2: Make Go ApiResult.Data nullable (*T pointer type) - #5: Dart caCertPath defaults to null instead of empty string - #9: Add toCookieValue to ObjectSerializer in all 12 languages - #14: Dart DefaultApiClient uses caCertPath with SecurityContext - #15: Fix Dart redirect handling (autoRedirect + maxRedirects) - #18: Route Dart/Rust path params through ValueSerializer.serializeStyled() - #26: Add default value support in Go, Rust, Swift, Dart, Elixir models - #35: Update Go version to 1.26 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
b4d5152 to
1c15042
Compare
The protobuf-duration migration left ISO-8601 duration assertions in the Swift, Dart and Elixir test templates (the serializer emits "5400s" / "0s" / "-300s", not "PT1H30M"). Rewrite every duration test in those languages to protobuf-JSON values and assertions; the reject cases now feed ISO-8601 strings and expect a parse error. Verified locally: Swift, Dart and Elixir ClientSpec all pass.
…ements Structural invariants (one source file = one test file; identical docs/shape; idempotency), a 10th test-parity dimension, per-finding why_not_surfaced + why_not_caught fields, multi-round loop-until-dry, and a hard WONTFIX deny-list.
…/AK/AU-resid/N1) Code fixes: csharp/node/swift/elixir AL decompression-error wrapping; node+dart N1 redirect body-replay guard scoped to 307/308; php AU-resid discriminator throw. Identical canonical tests for all 5 findings added across all 12 SDKs per the fix-time parity rule. Goldens not yet regenerated.
swift: AL decompression guard now gates on gzip magic bytes (Linux URLSession auto-decompresses but leaves the Content-Encoding header, so the residual-header heuristic wrongly threw on every response); platform-guarded zlib decode. rust/elixir: N1 302-proceeds test asserted the guard predicate deterministically instead of a chasm round-trip (chasm can't model https->http; returned 405).
…ats (D1/U1/U2/D2) D1: standalone Bearer + ApiKey authenticator tests in the 11 non-java SDKs. U1: ServerConfiguration + ServerVariable tests across all 12. U2: ApiResult tests across all 12. D2: README Caveats section added to java/kotlin/csharp/python/rust. Each new test registered in its Better<Lang>Codegen; all 12 ClientSpecs green.
The Gap AL guard used full-line // comments in DefaultApiClient; the swift and node FormattingSpec (generatedCodeShouldNotContainInlineComments) require block /* */ comments in generated production code. Convert them; behaviour unchanged.
…R5-1) Plus fleet-wide parity tests, identical across all 12: - R5-1: config-default-header-precedence test (red in ruby pre-fix, green elsewhere). - P1: rust gets a dedicated server_variable_test (split from server_configuration_test). - P2: BOM-tolerance test in all 12 (kotlin previously stripped a BOM with no test). Full per-language spec suite green for all 12.
…2-1); harmonize empty-Accept to "" (R13-1) R12-1: python/api/api.mustache gates the options default on nullable (like ruby) so an op whose Options has required fields requires the argument — matching the other 11. R13-1: select_accept_header returns "" (not null) in python/kotlin/csharp/node/elixir, with the consumer gated on non-empty in lockstep so an empty result still omits Accept; canonical empty-Accept test aligned across all 12. Full per-language spec suite green.
The SDK's true floor is Elixir 1.17 (it uses the stdlib Duration struct, added in 1.17); the runtime deps (req/jason/mime) all support it. Drops the floor from 1.19 to 1.17 — a 2-version reach gain. ElixirClientSpec green.
…ility The 3.4 floor was arbitrary; the source uses no 3.2+ feature and the runtime deps (faraday 2.0, dry-struct/dry-types 1.6/1.7, iso8601, tod) all support Ruby 3.1. Drops the floor 3.4 -> 3.1 (reach gain 3.1/3.2/3.3/3.4). RubyClientSpec green.
Package.swift declared only .macOS(.v14), so the SDK couldn't be added to iOS/ tvOS/watchOS app targets via SwiftPM. Declare all four Apple platforms at the async-URLSession API floor (macOS 12 / iOS 15 / tvOS 15 / watchOS 8). Linux/ Windows are unaffected (SwiftPM only gates Apple platforms). SwiftClientSpec green.
Extract the transport-agnostic orchestration (security-aware redirect loop, response decompression, charset decoding, header injection) into a new AbstractApiClient behind a single execute() seam. DefaultApiClient keeps the Symfony transport unchanged; a new Psr18ApiClient lets callers drive the SDK with any PSR-18 client (Guzzle, Symfony adapter, Laravel, a mock) while reusing that single-sourced orchestration. The client facade now accepts an optional custom ApiClient. Adds a Psr18ApiClientUnitTest that mirrors the DefaultApiClient behaviours through the PSR-18 path.
Extract the transport-agnostic orchestration (security-aware redirect loop, multipart encoding, response decompression, charset decoding, header injection) into a new AbstractApiClient built on Web-standard fetch/crypto/DecompressionStream. Two thin subclasses supply only the dispatcher: the undici-backed Node transport (static node:*/undici imports, full proxy/CA/TLS support) and a portable Fetch transport that imports nothing Node-specific. The package's #transport subpath import resolves the right one per runtime, so the SDK now loads on Deno, Bun, and edge runtimes (Cloudflare Workers, Vercel Edge), not just Node. undici becomes an optionalDependency. Adds a web-api-client test covering the portable variant.
Extract the transport-agnostic orchestration (security-aware redirect loop, multipart encoding, charset decoding, header injection) into a new AbstractApiClient written against package:http only, with no dart:io. Two thin subclasses supply the platform client and decompression: the native dart:io IOClient transport (full proxy/CA/TLS support) and a portable BrowserClient transport that imports no dart:io. A conditional export in default_api_client.dart resolves the right one per target, so the SDK now compiles and runs on Flutter Web (and dart2js/wasm), not just native. Importers are unchanged; the io/web files re-export the shared multipart helpers. No new pub dependencies.
The generated client targeted net10.0, excluding net8.0 (LTS) where most production C# and Unity run. Two net9+ APIs forced the floor: the [JsonStringEnumMemberName] enum attribute and System.Threading.Lock. Replace [JsonStringEnumMemberName]/JsonStringEnumConverter with a uniform generated per-enum JsonConverter<TEnum> (top-level and inline enums) that maps each member to its wire string explicitly -- net8-compatible, AOT-safe, and behaviour-preserving (unknown values throw JsonException). Swap System.Threading.Lock for a plain object lock. Drop TargetFramework to net8.0 and LangVersion to 12. The test project carries RollForward=Major so the net8 test host still runs on a newer-major-only runtime; the shipped library stays pure net8.
The generated client targeted Java 25 via <release>25</release>, excluding the widely-deployed LTS releases 17 and 21. The only API above 17 the code uses is HttpClient.close() (added in Java 21), so the true floor is 21, not 25. Lower <release> to 21 and update the README. The build still runs on JDK 25 and emits Java 21 bytecode, which runs on any JDK 21+.
The crate targeted edition 2024, which forces rust-version 1.85 (the newest toolchain). The source uses no edition-2024-specific features, so lower it to edition 2021 and declare MSRV 1.75 (the floor the tokio 1 / reqwest 0.12 dependency tree needs), widening support to older Rust toolchains.
Generated Jackson-based clients fail at runtime in a GraalVM native image because the model POJOs (and their inline enums) have no reflection metadata, so Jackson cannot (de)serialize them. The generator already knows every model it emits, so it now writes a reflect-config.json under META-INF/native-image registering each model class and nested inline enum for reflection. Verified end-to-end: a native-image build of the generated SDK round-trips a Pet (including its nested status enum's custom wire value) where it previously crashed with a missing-reflection error. The metadata is a build-time resource only and does not affect the JVM build.
Add AbstractWasmSpec, a shared spec a language opts into by supplying its wasm/WASI build command; it asserts the generated SDK compiles for a WebAssembly target. Wire the two toolchains proven wasm-clean: GoWasmSpec (GOOS=wasip1 go build) and DartWasmSpec (dart compile wasm of a probe that forces the BrowserClient web transport). Languages whose toolchain or transport is not wasm-capable simply do not subclass it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds 7 new language generators (Kotlin, Go, Rust, Dart, Swift, Elixir, C#) alongside the existing 5 (Java, Python, Ruby, PHP, Node/TypeScript) to produce fully harmonised, ergonomic client SDKs from any OpenAPI 3.0 spec. Every generated SDK shares the same architecture: BaseApi, DefaultApiClient, ObjectSerializer, ValueSerializer, HeaderSelector, Configuration, structured exceptions, per-operation Options classes, authentication (API key, Basic, Bearer, OAuth2), OpenTelemetry propagation, HTTP compression, TLS/proxy transport options, binary upload/download, and per-operation server overrides.
Motivation and Context
The default OpenAPI Generator templates produce inconsistent, non-idiomatic code across languages. This PR replaces them with a unified set of Mustache templates that generate production-grade SDKs on par with hand-written clients from Stripe, Stainless, or Speakeasy — fully linted, statically analysed, formatted, and integration-tested in Docker.
How Has This Been Tested?
All 12 SDKs are generated on-the-fly during the Maven build. Each SDK runs a full test suite inside Docker covering unit tests, integration tests against a live Petstore mock, formatting checks, linting, and static analysis. Regression tests for HeaderSelector and ValueSerializer ensure cross-language parity.
Checklist